import PluginsLoader from "../../../lib/plugins/loader.js"
import Botw from "./Botw.js"
import getFaceName from "./FaceMap.js"
import fs from "node:fs"
import url from "node:url"

const Botname = global.Bot.nickname
export default class Bott extends Botw {
    #configFile

    constructor(config) {
        super({
            appId: config.botConfig.appId,
            token: config.botConfig.token
        })

        this.#configFile = config.file
        this.autoStart = config.autoStart
        this.botConfig = config.botConfig
        this.cmdConfig = {
            cMsg: config.cmdConfig.cMsg,
            cList: new Set(config.cmdConfig.cList)
        }

        if (this.autoStart) this.start()
    }

    get configFile() {
        return this.#configFile
    }

    async start() {
        let config = {
            sandbox: this.botConfig.sandbox,
            intents: 0 | 1 << 0 | 1 << 1 | 1 << 12
        }

        if (this.botConfig.allMsg) {
            config.intents |= 1 << 9
        } else {
            config.intents |= 1 << 30
        }

        this.init(config, (msg) => {
            switch (msg.t) {
                case "GUILD_CREATE":
                    this.hGuildCreate(msg.d)
                    return
                case "GUILD_UPDATE":
                    this.hGuildUpdate(msg.d)
                    return
                case "GUILD_DELETE":
                    this.hGuildDelete(msg.d)
                    return
                case "GUILD_MEMBER_ADD":
                    this.hMemberAdd(msg.d)
                    return
                case "GUILD_MEMBER_REMOVE":
                    this.hMemberRemove(msg.d)
                    return
                case "MESSAGE_CREATE":
                    this.hMsgCreate(msg.d)
                    return
                case "MESSAGE_DELETE":
                    this.hMsgDelete(msg.d)
                    return
                case "AT_MESSAGE_CREATE":
                    this.hMsgCreate(msg.d)
                    return
                case "PUBLIC_MESSAGE_DELETE":
                    this.hMsgDelete(msg.d)
                    return
                case "DIRECT_MESSAGE_CREATE":
                    this.hDmsCreate(msg.d)
                    return
                case "DIRECT_MESSAGE_DELETE":
                    this.hDmsDelete(msg.d)
                    return
                default:
                    logger.debug(`[QQ频道插件][${this.botName}] 收到消息(未处理).`, msg)
            }
        })
    }

    async hGuildCreate(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 加入频道`, msg)
        await this.getBotGuilds()
    }

    async hGuildUpdate(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 频道.资料变更`, msg)
        await this.getBotGuilds()
    }

    async hGuildDelete(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 退出频道`, msg)
        await this.getBotGuilds()
    }

    async hMemberAdd(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 频道.加入成员`, msg)
        // TODO ........
    }

    async hMemberRemove(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 频道.成员退出`, msg)
        // TODO ........
    }

    async hMsgCreate(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 子频道.收到消息`, msg)
        await this.callPlugs(msg)
    }

    async hMsgDelete(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 子频道.撤回消息`, msg)
        // TODO ........
    }

    async hDmsCreate(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 私信.收到消息`, msg)
        await this.callPlugs(msg, true)
    }

    async hDmsDelete(msg) {
        logger.debug(`[QQ频道插件][${this.botName}] 私信.撤回消息`, msg)
        // TODO ........
    }

    async callPlugs(msg, isDms) {
        if (!msg.content) {
            logger.debug(`[QQ频道插件][${this.botName}] 跳过消息.`, msg)
            return
        }

        if (this.cmdConfig.cList.size > 0) {
            let cmd = msg.content
                .replace(/\<@!\d+>/g, "")
                .replace(/\s/g, "")
                .replace(/^#+/, "")

            if (this.cmdConfig.cList.has(cmd)) {
                logger.debug(`[QQ频道插件][${this.botName}] 频道.过滤命令.`, cmd)

                if (!this.cmdConfig.cMsg?.length) return
                if (msg.content.includes(`<@!${this.botId}>`)) {
                    await this.postMsg(
                        isDms ? msg.guild_id : msg.channel_id,
                        {
                            msg_id: msg.id,
                            content: this.cmdConfig.cMsg
                        },
                        isDms
                    )
                }

                return
            }
        }

        let e = this.makee(msg, isDms)
        if (e) await PluginsLoader.deal(e)
    }

    makee(msg, isDms) {
        let e = isDms ? this.makeePrivate(msg) : this.makeeGroup(msg)

        e.toString = () => {
            return msg.content
                .replace(new RegExp(`\\<@!${this.botId}>`, "g"), `{at:${Bot.uin}}`)
                .replace(/\<emoji:(\d+)>/g, "{face:$1}")
                .replace(/\<@!(\d+)>/g, "{at:$1}")
        }

        e.reply = async (m) => {
            logger.debug(`[QQ频道插件][${this.botName}] 回复消息.`, m)

            let rMsg = { msg_id: msg.id }

            let addImg = (f) => {
                if (Buffer.isBuffer(f)) {
                    rMsg.file = f
                    return
                }

                if (typeof f != "string") return false

                let p = f

                if (/^file:/i.test(f)) {
                    p = f.replace(/^file:\/\//i, "")
                    if (!fs.existsSync(p)) {
                        p = f.replace(/^file:\/\/\//i, "")
                        if (!fs.existsSync(p)) {
                            try {
                                p = url.fileURLToPath(f)
                            } catch (err) {
                                logger.debug(`[QQ频道插件][${this.botName}] 跳过转制图片(File协议不正确).`, f, err)
                            }
                        }
                    }
                }

                if (!fs.existsSync(p)) return false

                rMsg.file_image = p
            }

            let addMsg = (m) => {
                let content = ""
                switch (typeof m) {
                    case "string":
                        content += m
                        break
                    case "number":
                        content += `${m}`
                        break
                    case "object":
                        switch (m.type) {
                            case "text":
                                content += m.text
                                break
                            case "face":
                                content += `<emoji:${m.id}>`
                                break
                            case "at":
                                if (m.id) {
                                    content += `<@!${m.id}>`
                                } else {
                                    content += m.qq == parseInt(e.user_id) ? `<@!${e.user_id}>` : m.text
                                }
                                break
                            case "image":
                                if (addImg(m.file) === false) {
                                    logger.debug(`[QQ频道插件][${this.botName}] 跳过回复消息转制(图片).`, m)
                                }
                                break
                            case "xml":
                                if (m.data.startsWith("<?xml ")) {
                                    content += m.data
                                        .replace(/\<.+?>/g, "\n")
                                        .replace(/(\r?\n)+/g, "\n")
                                        .replaceAll(`${Botname}: `, "")
                                        .replaceAll("转发的聊天记录", "")
                                        .replaceAll(/查看\d+条转发消息/g, "")
                                } else {
                                    content += m.data
                                        .replaceAll("{\\n}", "\n")
                                        .replace(/(\r?\n)+/g, "\n")
                                }
                                break
                            default:
                                if (Array.isArray(m)) {
                                    for (let v of m) content += addMsg(v)
                                } else {
                                    logger.debug(`[QQ频道插件][${this.botName}] 跳过回复消息转制(无法识别).`, m)
                                }
                        }
                        break
                    default:
                        logger.debug(`[QQ频道插件][${this.botName}] 跳过回复消息转制(无法识别).`, m)
                }

                return content
            }

            let content = addMsg(m).trim()

            if (content.length) rMsg.content = content

            if (!rMsg.content && !rMsg.file_image && !rMsg.file) return {}

            logger.debug(`[QQ频道插件][${this.botName}] 转制回复消息.`, rMsg)

            let rsp = await this.postMsg(isDms ? msg.guild_id : msg.channel_id, rMsg, isDms)
            logger.debug(`[QQ频道插件][${this.botName}] 回复消息结果.`, rsp)

            if (!rsp?.timestamp) {
                return {}
            }

            return {
                seq: rsp.seq_in_channel,
                rand: 10000000,
                time: parseInt(Date.parse(rsp.timestamp) / 1000),
                message_id: rsp.id
            }
        }

        logger.debug(`[QQ频道插件][${this.botName}] 转制消息.`, e)

        return e
    }

    makeePrivate(msg) {
        let time = parseInt(Date.parse(msg.timestamp) / 1000)
        let message = this.makeeMessage(msg)
        return {
            ...message,
            post_type: "message",
            message_id: msg.id,
            user_id: msg.author.id,
            time,
            message_type: "private",
            sub_type: "group",
            sender: {
                avatar: msg.author.avatar,
                user_id: msg.author.id,
                nickname: msg.author.username,
                group_id: msg.src_guild_id,
                discuss_id: undefined
            },
            from_id: msg.author.id,
            to_id: Bot.uin,
            font: "宋体",
            seq: msg.seq,
            rand: 10000000,
            auto_reply: false,
            self_id: Bot.uin,
            friend: {
                recallMsg: async (msg_id) => {
                    logger.debug(`[QQ频道插件][${this.botName}] e.friend.recallMsg`, msg_id)
                    if (typeof msg_id === "string") {
                        await this.delMessage(msg.guild_id, msg_id, true)
                    }
                },
                makeForwardMsg: async (forwardMsg) => {
                    logger.debug(`[QQ频道插件][${this.botName}] e.friend.makeForwardMsg`, forwardMsg)
                    let retXml = {
                        type: "xml",
                        data: "",
                        id: 1000
                    }
                    for (let x of forwardMsg) {
                        if (Array.isArray(x.message)) {
                            retXml.data += x.message.join("{\\n}").replace(/\r?\n/g, "{\\n}") + "{\\n}"
                        } else {
                            retXml.data += x.message.replace(/\r?\n/g, "{\\n}") + "{\\n}"
                        }
                    }
                    return retXml
                }
            }
        }
    }

    makeeGroup(msg) {
        let time = parseInt(Date.parse(msg.timestamp) / 1000)
        let role = msg.member.roles.includes("4") ? "owner" : msg.member.roles.includes("2") ? "admin" : "member"
        let message = this.makeeMessage(msg)
        let atme = false

        for (let x of message.message) {
            if (x.type === "at" && x.qq === Bot.uin) {
                atme = true
                break
            }
        }

        return {
            ...message,
            post_type: "message",
            message_id: msg.id,
            user_id: msg.author.id,
            time,
            message_type: "group",
            sub_type: "normal",
            sender: {
                avatar: msg.author.avatar,
                user_id: msg.author.id,
                nickname: msg.author.username,
                card: msg.author.username,
                sex: "unknown",
                area: "",
                title: "",
                level: 100,
                age: 100,
                role
            },
            block: false,
            anonymous: null,
            atall: msg.mention_everyone || false,
            group_id: msg.guild_id,
            group_name: this.getGuildName(msg.guild_id),
            self_id: Bot.uin,
            font: "宋体",
            seq: msg.seq,
            rand: 10000000,
            atme,
            member: {
                info: {
                    group_id: msg.guild_id,
                    user_id: msg.author.id,
                    nickname: msg.author.username,
                    card: msg.author.username,
                    sex: "unknown",
                    age: 100,
                    area: "",
                    level: 100,
                    rank: "",
                    role,
                    title: "",
                    title_expire_time: 0,
                    shutup_time: 0,
                    update_time: 0,
                    join_time: 0,
                    last_sent_time: time
                },
                group_id: msg.guild_id,
                is_admin: role === "owner" || role === "admin",
                is_owner: role === "owner"
            },
            group: {
                pickMember: (id) => {
                    if (id == msg.author.id) {
                        return {
                            info: {
                                card: msg.author.username,
                                nickname: msg.author.username
                            },
                            getAvatarUrl: (...args) => {
                                return msg.author.avatar
                            }
                        }
                    }
                },
                recallMsg: async (msg_id) => {
                    logger.debug(`[QQ频道插件][${this.botName}] e.group.recallMsg`, msg_id)
                    if (typeof msg_id === "string") {
                        await this.delMessage(msg.channel_id, msg_id, false)
                    }
                },
                makeForwardMsg: async (forwardMsg) => {
                    logger.debug(`[QQ频道插件][${this.botName}] e.group.makeForwardMsg`, forwardMsg)
                    let retXml = {
                        type: "xml",
                        data: "",
                        id: 1000
                    }
                    for (let x of forwardMsg) {
                        if (Array.isArray(x.message)) {
                            retXml.data += x.message.join("{\\n}").replace(/\r?\n/g, "{\\n}") + "{\\n}"
                        } else {
                            retXml.data += x.message.replace(/\r?\n/g, "{\\n}") + "{\\n}"
                        }
                    }
                    return retXml
                }
            },
            recall: async () => {
                logger.debug(`[QQ频道插件][${this.botName}] e.recall`)
                await this.delMessage(msg.channel_id, msg.id, false)
            }
        }
    }

    makeeMessage(msg) {
        let message = []
        let raw_message = msg.content
        let rex_message = msg.content
        let rex = /(?<t>\<((?<at>@!)|(?<face>emoji):)(?<id>\d+)>)/

        let getAtName = (i) => {
            for (let n of msg.mentions) if (n.id === i) {
                return `@${n.username}`
            }
        }

        while (rex) {
            let r = rex.exec(rex_message)

            if (!r) {
                if (rex_message.length) message.push({ type: "text", text: rex_message })
                break
            }

            if (r.index) message.push({ type: "text", text: rex_message.slice(0, r.index) })

            rex_message = rex_message.slice(r.index + r.groups.t.length)

            if (r.groups.at) {
                let qq = r.groups.id
                let text = getAtName(r.groups.id)
                if (r.groups.id === this.botId) qq = Bot.uin
                raw_message = raw_message.replace(r.groups.t, text)
                message.push({ type: "at", qq, text })
                continue
            }

            if (r.groups.face) {
                let text = getFaceName(r.groups.id)
                raw_message = raw_message.replace(r.groups.t, `[${text}]`)
                message.push({ type: "face", id: r.groups.id, text })
                continue
            }

            
        }

        return { message, raw_message }
    }
}
